/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.func.impl;

import com.je.common.base.DynaBean;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.spring.SpringContextHolder;
import com.je.common.base.util.*;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.model.dd.DictionaryItemVo;
import com.je.meta.rpc.dictionary.DictionaryRpcService;
import com.je.meta.service.DataImplService;
import net.sf.json.JSONObject;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @program: jecloud-meta
 * @author: LIULJ
 * @create: 2021/8/10
 * @description:
 */
@Service
public class DataImplServiceImpl implements DataImplService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private DictionaryRpcService dictionaryRpcService;


    @Override
    public List<DynaBean> implData(String filePath, JSONObject returnObj) {
        FileInputStream fis = null;
        POIFSFileSystem fs = null;
        HSSFWorkbook wb = null;
        JSONObject params = new JSONObject();
        int sheetIndex = 0;
        if (returnObj.containsKey("sheet")) {
            if (StringUtil.isNotEmpty(returnObj.get("sheet") + "")) {
                sheetIndex = returnObj.getInt("sheet");
            }
        }
        if (returnObj.containsKey("params")) {
            params = returnObj.getJSONObject("params");
        }
        try {
            // 1.得到文件对象
            fis = new FileInputStream(filePath);
            fs = new POIFSFileSystem(fis);
            wb = new HSSFWorkbook(fs);
        } catch (FileNotFoundException e1) {
            throw new PlatformException("文件读取出错", PlatformExceptionEnum.JE_CORE_EXCEL_READFILE_ERROR, new Object[]{filePath, returnObj}, e1);
//			returnObj.put("error", "文件读取出错!");
//			return null;
        } catch (IOException e1) {
            throw new PlatformException("文件读取出错", PlatformExceptionEnum.JE_CORE_EXCEL_READFILE_ERROR, new Object[]{filePath, returnObj}, e1);
//			returnObj.put("error", "文件读取出错!");
//			return null;
        }
        // 报表封面
        HSSFSheet sheet = wb.getSheetAt(sheetIndex);
        HSSFCell nowCell = null;
        Integer success = 0;
        Integer failure = 0;
        List<String> failures = new ArrayList<String>();
        //获取模版主键
        nowCell = getCell(sheet, 1, 1);
        String templateId = getCellStringValue(nowCell);
        if (StringUtil.isEmpty(templateId)) {
            returnObj.put("error", "未发现模版信息，请重新下载模版...");
            return null;
        }
        DynaBean template = metaService.selectOneByPk("JE_SYS_DATATEMPLATE", templateId);
        if (template == null) {
            returnObj.put("error", "未在系统查到模版信息，请查看系统模版内容...");
            return null;
        }
        if (!templateId.equals(returnObj.getString("pkValue"))) {
            returnObj.put("error", "数据信息与当前模版不对应，请重新下载模版...");
            return null;
        }
        List<DynaBean> allFields = metaService.select("JE_SYS_DATAFIELD",
                ConditionsWrapper.builder().apply("JE_SYS_DATATEMPLATE_ID={0} ORDER BY DATAFIELD_HIDDEN ASC,SY_ORDERINDEX ASC", templateId));
        List<DynaBean> fields = new ArrayList<DynaBean>();
        Map<String, DynaBean> fieldInfos = new HashMap<String, DynaBean>();
        Map<String, List<DictionaryItemVo>> dicInfos = new HashMap<String, List<DictionaryItemVo>>();
        for (DynaBean field : allFields) {
            if ("cbbfield".equals(field.getStr("DATAFIELD_XTYPE"))) {
                String configInfo = field.getStr("DATAFIELD_CONFIGINFO", "");
                if (StringUtil.isNotEmpty(configInfo)) {
                    //获取字典数据
                    String ddCode = configInfo.split(ArrayUtils.SPLIT)[0];
                    List<DictionaryItemVo> dicItems = dictionaryRpcService.getDicList(ddCode, new Query(), false);
                    dicInfos.put(ddCode, dicItems);
                }
            }
            if (!"1".equals(field.getStr("DATAFIELD_HIDDEN"))) {
                fields.add(field);
                fieldInfos.put(field.getStr("DATAFIELD_NAME"), field);
            }
        }

        //计算出数据模版列的的顺序集合
        List<DynaBean> columns = new ArrayList<DynaBean>();
        for (int i = 0; i < fields.size(); i++) {
            nowCell = getCell(sheet, 2 + i, 3);
            if (nowCell == null) {
                break;
            }
            String fieldName = getCellStringValue(nowCell);
            if (StringUtil.isEmpty(fieldName)) {
                nowCell = getCell(sheet, 2 + i, 2);
                fieldName = getCellStringValue(nowCell);
            }
            DynaBean field = fieldInfos.get(fieldName);
            if (field == null) {
                returnObj.put("error", "模版标题【" + fieldName + "】在系统未找到，请重新下载模版!");
                return null;
            }
            columns.add(field);
        }
        if (columns.size() <= 0) {
            returnObj.put("error", "模版标题不符合格式，请重新下载模版!");
            return null;
        }
        //执行前置sql
        String sqlStr = template.getStr("DATATEMPLATE_BEFORESQL", "");
        if (StringUtil.isNotEmpty(sqlStr)) {
            String[] sqls = sqlStr.split(";");
            for (String sql : sqls) {
                if (StringUtil.isNotEmpty(sql)) {
                    try {
                        metaService.executeSql(sql);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        int startRow = 4;
        if ("1".equals(template.getStr("DATATEMPLATE_SM_CODE"))) {
            startRow = 5;
        }
        List<DynaBean> results = new ArrayList<DynaBean>();
        for (int row = startRow; row <= (sheet.getLastRowNum() + 1); row++) {
            HSSFRow rowObj = sheet.getRow(row - 1);
            DynaBean dynaBean = new DynaBean(template.getStr("DATATEMPLATE_TABLECODE"), true);
            if (rowObj == null) {
                continue;
            }
            boolean btError = false;
            for (int col = 0; col < columns.size(); col++) {
                DynaBean column = columns.get(col);
                String fieldCode = column.getStr("DATAFIELD_CODE");
                String xtype = column.getStr("DATAFIELD_XTYPE");
                nowCell = getCell(sheet, col + 2, row);
                String defaultValue = column.getStr("DATAFIELD_VALUE");
                String val = "";
//				if(nowCell==null){
//					if(StringUtil.isNotEmpty(defaultValue)){
//						dynaBean.set(fieldCode, StringUtil.codeToValue(defaultValue));
//					}
//					continue;
//				}
                if (nowCell != null) {
                    val = getCellStringValue(nowCell);
                    if ("datetimefield".equals(xtype) || "datefield".equals(xtype)) {
                        if (StringUtil.isNotEmpty(val)) {
                            Date d = DateUtils.getDate(val, DateUtils.DAFAULT_DATETIME_FORMAT);
                            if (d == null) {
                                DateUtils.getDate(val, DateUtils.DAFAULT_DATE_FORMAT);
                            }
                            if (d != null) {
                                if ("datetimefield".equals(xtype)) {
                                    val = DateUtils.formatDateTime(d);
                                } else if ("datefield".equals(xtype)) {
                                    val = DateUtils.formatDate(d);
                                }
                            }
                        }
                    }
                }
                if (StringUtil.isNotEmpty(defaultValue)) {
                    defaultValue = StringUtil.codeToValue(defaultValue);
                }
                if (StringUtil.isEmpty(val)) {
                    val = defaultValue;
                }
                if ("1".equals(column.getStr("DATAFIELD_EMPTY"))) {
                    if (StringUtil.isEmpty(val)) {
                        btError = true;
                        failure++;
                        failures.add("第" + row + "行：【" + column.getStr("DATAFIELD_NAME") + "】列为必填项。");
                        break;
                    }
                }
                if (StringUtil.isNotEmpty(val) && "1".equals(column.getStr("DATAFIELD_QCKXJS"))) {
                    String regx = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$";
                    Pattern pattern = Pattern.compile(regx);
                    if (pattern.matcher(val).matches()) {
//						 DecimalFormat df = new DecimalFormat("0");
//						 val = df.format(val);
                        BigDecimal b = new BigDecimal(val);
                        val = b.toPlainString();
                    }
                }
                if ("textfield".equals(xtype)) {
                    dynaBean.set(fieldCode, val);
                    //下拉框
                } else if ("cbbfield".equals(xtype)) {
                    String configInfo = column.getStr("DATAFIELD_CONFIGINFO", "");
                    if (StringUtil.isNotEmpty(configInfo)) {
                        //获取字典数据
                        String[] configs = configInfo.split(ArrayUtils.SPLIT);
                        String ddCode = configs[0];
                        List<DictionaryItemVo> dicItems = dicInfos.get(ddCode);
                        if (dicItems != null && StringUtil.isNotEmpty(val)) {
                            //找到字典项
                            DictionaryItemVo dicItem = null;
                            for (DictionaryItemVo item : dicItems) {
                                if (val.equals(item.getText())) {
                                    dicItem = item;
                                    break;
                                }
                            }
                            if (dicItem != null) {
                                String[] configFs = null;
                                String[] configDs = null;
                                if (configs.length > 2) {
                                    configFs = configs[1].split("~");
                                    configDs = configs[2].split("~");
                                    for (int i = 0; i < configFs.length; i++) {
                                        String fc = configFs[i];
                                        String dc = configDs[i];
                                        if ("text".equals(dc)) {
                                            dynaBean.set(fc, dicItem.getText());
                                        } else if ("code".equals(dc)) {
                                            dynaBean.set(fc, dicItem.getCode());
                                        } else if ("id".equals(dc)) {
                                            dynaBean.set(fc, dicItem.getId());
                                        }
                                    }
                                } else {
                                    dynaBean.set(fieldCode, dicItem.getCode());
                                }
                            } else {
                                dynaBean.set(fieldCode, val);
                            }
                        } else {
                            dynaBean.set(fieldCode, val);
                        }
                    }
                } else {
                    dynaBean.set(fieldCode, val);
                }
            }
            for (DynaBean field : allFields) {
                if ("1".equals(field.getStr("DATAFIELD_HIDDEN"))) {
                    String fieldCode = field.getStr("DATAFIELD_CODE");
                    String xtype = field.getStr("DATAFIELD_XTYPE");
                    String defaultValue = field.getStr("DATAFIELD_VALUE");
                    if (StringUtil.isNotEmpty(dynaBean.getStr(fieldCode))) {
                        continue;
                    }
                    if (ArrayUtils.contains(new String[]{"textfield", "cbbfield"}, xtype)) {
                        if (StringUtil.isNotEmpty(defaultValue)) {
                            field.set(fieldCode, StringUtil.codeToValue(defaultValue));
                        }
                    }
                }
            }
            if (btError) {
                continue;
            }
            if ("1".equals(template.getStr("DATATEMPLATE_ZDXTFIELD"))) {
                commonService.buildModelCreateInfo(dynaBean);
            }
            String beforeClass = template.getStr("DATATEMPLATE_CZQLM");
            String beforeMethod = template.getStr("DATATEMPLATE_CZQFF");
            dynaBean.set("NOW_ROW", row);
            dynaBean.set("params", params);
            if (StringUtil.isNotEmpty(beforeClass) && StringUtil.isNotEmpty(beforeMethod)) {
                //处理前执行类
                Object bean = SpringContextHolder.getBean(beforeClass);
                dynaBean = (DynaBean) ReflectionUtils.getInstance().invokeMethod(bean, beforeMethod, new Object[]{dynaBean});
                if (dynaBean == null) {
                    returnObj.put("error", "操作前方法必须返回DynaBean数据对象");
                    return null;
                } else {
                    if (dynaBean.containsKey("error")) {
                        returnObj.put("error", dynaBean.getStr("error", ""));
                        return null;
                    }
                }
            }
            //如果不做处理
            if (!"1".equals(template.getStr("DATATEMPLATE_BZCZ"))) {
                try {
                    //如果包含修改操作
                    if ("1".equals(template.getStr("DATATEMPLATE_XGCZ"))) {
                        String fieldCodes = template.getStr("DATATEMPLATE_WYZDBM", "");
                        if (StringUtil.isNotEmpty(fieldCodes)) {
                            String[] fieldArray = fieldCodes.split(ArrayUtils.SPLIT);
                            String[] unSqls = new String[fieldArray.length];
                            boolean yxdata = false;
                            for (int i = 0; i < fieldArray.length; i++) {
                                unSqls[i] = " " + fieldArray[i] + "='" + dynaBean.getStr(fieldArray[i]) + "' ";
                                if (StringUtil.isNotEmpty(dynaBean.getStr(fieldArray[i]))) {
                                    yxdata = true;
                                }
                            }
                            if (!yxdata) {
//								failure++;
//								failures.add("第"+row+"行：唯一字段的值为空。");
                                continue;
                            }
                            List<DynaBean> lists = metaService.select(template.getStr("DATATEMPLATE_TABLECODE"),
                                    ConditionsWrapper.builder().apply(StringUtil.buildSplitString(unSqls, " AND ")));
                            if (lists.size() == 1) {
                                dynaBean.set(dynaBean.getStr(BeanService.KEY_PK_CODE), lists.get(0).getStr(dynaBean.getStr(BeanService.KEY_PK_CODE)));
                                commonService.buildModelModifyInfo(dynaBean);
                                metaService.update(dynaBean);
                            } else if (lists.size() > 1) {
                                failure++;
                                failures.add("第" + row + "行：数据根据唯一字段查询出重复数据。");
                                continue;
                            } else {
                                metaService.insert(dynaBean);
                            }
                        } else {
                            metaService.insert(dynaBean);
                        }
                    } else {
                        metaService.insert(dynaBean);
                    }
                    success++;
                } catch (Exception e) {
                    e.printStackTrace();
                    failure++;
                    String message = e.getMessage();
                    if (StringUtil.isNotEmpty(message)) {
                        message = message.replaceAll("'", "");
                    }
                    failures.add("第" + row + "行：" + message);
                }
            }
            String afterClass = template.getStr("DATATEMPLATE_CZHLM");
            String afterMethod = template.getStr("DATATEMPLATE_CZHFF");
            if (StringUtil.isNotEmpty(afterClass) && StringUtil.isNotEmpty(afterMethod)) {
                Object bean = SpringContextHolder.getBean(afterClass);
                DynaBean result = (DynaBean) ReflectionUtils.getInstance().invokeMethod(bean, afterMethod, new Object[]{dynaBean});
                if (result == null) {
                    returnObj.put("error", "操作前方法必须返回DynaBean数据对象");
                    return null;
                } else {
                    if (dynaBean.containsKey("error")) {
                        returnObj.put("error", dynaBean.getStr("error", ""));
                        return null;
                    }
                }
            }
            results.add(dynaBean);
        }
        //执行前置sql
        sqlStr = template.getStr("DATATEMPLATE_AFTERSQL", "");
        if (StringUtil.isNotEmpty(sqlStr)) {
            String[] sqls = sqlStr.split(";");
            for (String sql : sqls) {
                if (StringUtil.isNotEmpty(sql)) {
                    try {
                        metaService.executeSql(sql);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        if ("1".equals(template.getStr("DATATEMPLATE_BZCZ"))) {
            returnObj.put("msg", "数据导入成功!");
            returnObj.put("msgType", "0");
        } else {
            if (failure > 0) {
                String errors = "<p>导入成功" + success + "条数据。</p><p>" + "导入失败" + failure + "条数据。</p>";
                errors += ("<p>" + StringUtil.buildSplitString(ArrayUtils.getArray(failures), "</p><p>") + "</p>");
                returnObj.put("msg", errors);
                returnObj.put("msgType", "1");
            } else {
                returnObj.put("msgType", "0");
                returnObj.put("msg", "数据导入成功!");
            }
        }
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                throw new PlatformException("文件流关闭流异常", PlatformExceptionEnum.JE_CORE_EXCEL_INPUTSTREAM_ERROR, new Object[]{filePath, returnObj}, e);
            }
        }
        return results;
    }

}
